/***************************************************************************************
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
*
* NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

/*#include <device/map.h>*/
/*#include "mmc.h"*/

/*// http://www.files.e-shop.co.il/pdastore/Tech-mmc-samsung/SEC%20MMC%20SPEC%20ver09.pdf*/

/*// see page 26 of the manual above*/
/*#define MEMORY_SIZE (16ull * 1024 * 1024 * 1024)  // 16GB*/
/*#define READ_BL_LEN 15*/
/*#define BLOCK_LEN (1 << READ_BL_LEN)*/
/*#define NR_BLOCK (MEMORY_SIZE / BLOCK_LEN)*/
/*#define C_SIZE_MULT 7  // only 3 bits*/
/*#define MULT (1 << (C_SIZE_MULT + 2))*/
/*#define C_SIZE (NR_BLOCK / MULT - 1)*/

/*// This is a simple hardware implementation of linux/drivers/mmc/host/bcm2835.c*/
/*// No DMA and IRQ is supported, so the driver must be modified to start PIO*/
/*// right after sending the actual read/write commands.*/

/*enum {*/
  /*SDCMD, SDARG, SDTOUT, SDCDIV,*/
  /*SDRSP0, SDRSP1, SDRSP2, SDRSP3,*/
  /*SDHSTS, __PAD0, __PAD1, __PAD2,*/
  /*SDVDD, SDEDM, SDHCFG, SDHBCT,*/
  /*SDDATA, __PAD10, __PAD11, __PAD12,*/
  /*SDHBLC*/
/*};*/

/*static FILE *fp = NULL;*/
/*static uint32_t *base = NULL;*/
/*static uint32_t blkcnt = 0;*/
/*static long blk_addr = 0;*/
/*static uint32_t addr = 0;*/
/*static bool write_cmd = 0;*/
/*static bool read_ext_csd = false;*/

/*static void prepare_rw(int is_write) {*/
  /*blk_addr = base[SDARG];*/
  /*addr = 0;*/
  /*if (fp) fseek(fp, blk_addr << 9, SEEK_SET);*/
  /*write_cmd = is_write;*/
/*}*/

/*static void sdcard_handle_cmd(int cmd) {*/
  /*switch (cmd) {*/
    /*case MMC_GO_IDLE_STATE: break;*/
    /*case MMC_SEND_OP_COND: base[SDRSP0] = 0x80ff8000; break;*/
    /*case MMC_ALL_SEND_CID:*/
      /*base[SDRSP0] = 0x00000001;*/
      /*base[SDRSP1] = 0x00000000;*/
      /*base[SDRSP2] = 0x00000000;*/
      /*base[SDRSP3] = 0x15000000;*/
      /*break;*/
    /*case 52: // ???*/
      /*break;*/
    /*case MMC_SEND_CSD:*/
      /*base[SDRSP0] = 0x92404001;*/
      /*base[SDRSP1] = 0x124b97e3 | ((C_SIZE & 0x3) << 30);*/
      /*base[SDRSP2] = 0x0f508000 | (C_SIZE >> 2) | (READ_BL_LEN << 16);*/
      /*base[SDRSP3] = 0x9026012a;*/
      /*break;*/
    /*case MMC_SEND_EXT_CSD: read_ext_csd = true; addr = 0; break;*/
    /*case MMC_SLEEP_AWAKE: break;*/
    /*case MMC_APP_CMD: break;*/
    /*case MMC_SET_RELATIVE_ADDR: break;*/
    /*case MMC_SELECT_CARD: break;*/
    /*case MMC_SET_BLOCK_COUNT: blkcnt = base[SDARG] & 0xffff; break;*/
    /*case MMC_READ_MULTIPLE_BLOCK: prepare_rw(false); break;*/
    /*case MMC_WRITE_MULTIPLE_BLOCK: prepare_rw(true); break;*/
    /*case MMC_SEND_STATUS: base[SDRSP0] = 0x900; base[SDRSP1] = base[SDRSP2] = base[SDRSP3] = 0; break;*/
    /*case MMC_STOP_TRANSMISSION: break;*/
    /*default:*/
      /*panic("unhandled command = %d", cmd);*/
  /*}*/
/*}*/

/*static void sdcard_io_handler(uint32_t offset, int len, bool is_write) {*/
  /*int idx = offset / 4;*/
  /*switch (idx) {*/
    /*case SDCMD: sdcard_handle_cmd(base[SDCMD] & 0x3f); break;*/
    /*case SDARG:*/
    /*case SDRSP0:*/
    /*case SDRSP1:*/
    /*case SDRSP2:*/
    /*case SDRSP3:*/
      /*break;*/
    /*case SDDATA:*/
       /*if (read_ext_csd) {*/
         /*// See section 8.1 JEDEC Standard JED84-A441*/
         /*uint32_t data;*/
         /*switch (addr) {*/
           /*case 192: data = 2; break; // EXT_CSD_REV*/
           /*case 212: data = MEMORY_SIZE / 512; break;*/
           /*default: data = 0;*/
         /*}*/
         /*base[SDDATA] = data;*/
         /*if (addr == 512 - 4) read_ext_csd = false;*/
       /*} else if (fp) {*/
         /*__attribute__((unused)) int ret;*/
         /*if (!write_cmd) { ret = fread(&base[SDDATA], 4, 1, fp); }*/
         /*else { ret = fwrite(&base[SDDATA], 4, 1, fp); }*/
       /*}*/
       /*addr += 4;*/
       /*break;*/
    /*default:*/
      /*Log("offset = 0x%x(idx = %d), is_write = %d, data = 0x%x", offset, idx, is_write, base[idx]);*/
      /*panic("unhandle offset = %d", offset);*/
  /*}*/
/*}*/

/*void init_sdcard() {*/
  /*base = (uint32_t *)new_space(0x80);*/
  /*add_mmio_map("sdhci", CONFIG_SDCARD_CTL_MMIO, base, 0x80, sdcard_io_handler);*/

  /*Assert(C_SIZE < (1 << 12), "shoule be fit in 12 bits");*/

  /*const char *img = CONFIG_SDCARD_IMG_PATH;*/
  /*fp = fopen(img, "r+");*/
  /*if (fp == NULL) Log("Can not find sdcard image: %s", img);*/
/*}*/
